//#include "stdafx.h"
#include "Global_Function.h"
#include "JsonRpcUtil.h"

#ifndef MAKEDEPEND
# include <ctype.h>
# include <iostream>
# include <fstream>
# include <stdarg.h>
# include <stdio.h>
# include <string.h>
#endif

#include "JsonRpc.h"
#include "define.h"
#include <fmt/format.h>

using namespace JsonRpc;


//#define USE_WINDOWS_DEBUG // To make the error and log messages go to VC++ debug output
#ifdef USE_WINDOWS_DEBUG
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

// Version id
const char JsonRpc::JSONRPC_VERSION[] = "JSONRPC++ 0.7";

// Default log verbosity: 0 for no messages through 5 (writes everything)
int JsonRpcLogHandler::_verbosity = 5;

// Default log handler
static class DefaultLogHandler : public JsonRpcLogHandler {
private:
    CStrings get_log_path() {
        static CStrings path;

        if (!path.IsEmpty())
            return path;

        char buf[500] = {0};
        //GetModuleFileName(NULL, buf, 500);
        //GetModuleFileName(buf, 500);

        CStrings strAppName(buf);
        int nPos = strAppName.ReverseFind('\\');
        path = strAppName.Mid(0, nPos)+"\\rpc_log.txt";
        return path;
    }

public:

    virtual void log(int level, const char *buf, int len){
        try
        {
            //CStdioFiles logFile(get_log_path(), CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite);
            //logFile.SeekToEnd();
            //logFile.Write(buf, len);
            //logFile.Close();
            std::ofstream ofs(get_log_path().string(), std::ios::app);
            ofs << std::string(buf, len);
        }
        catch(...)
        {
        }
    }

    void log(int level, const char* msg) {

        CStrings strInfo;
        SYSTEMTIME st;
        GetLocalTime(&st);
        //strInfo.Format("\r\n%4d/%02d/%02d %02d:%02d:%02d  %s",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond, msg);
        strInfo = fmt::format("\r\n{:04}/{:02}/{:02} {:02}:{:02}:{:02}  {}",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond, msg);
        log(level, strInfo.GetBuffer(0), strInfo.GetLength());
// #ifdef USE_WINDOWS_DEBUG
//     if (level <= _verbosity) { OutputDebugString(msg); OutputDebugString("\n"); }
// #else
//     if (level <= _verbosity) std::cout << msg << std::endl;
// #endif
    }
} defaultLogHandler;

// Message log singleton
JsonRpcLogHandler* JsonRpcLogHandler::_logHandler = &defaultLogHandler;


// Default error handler
static class DefaultErrorHandler : public JsonRpcErrorHandler {
public:

  void error(const char* msg) {

      char buf[500] = {0};
      //GetModuleFileName(NULL, buf, 500);
      //GetModuleFileName(buf, 500);
	  
      CStrings strAppName(buf);
      int nPos = strAppName.ReverseFind('\\');
      CStrings strLogDir = strAppName.Mid(0, nPos)+"\\rpc_log.txt";
	  
      try{
          //CStdioFiles logFile(strLogDir, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite);
          //logFile.SeekToEnd();
          CStrings strInfo;
          SYSTEMTIME st;
          GetLocalTime(&st);
          //strInfo.Format("\r\n%4d/%02d/%02d %02d:%02d:%02d  %s",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond, msg);
          strInfo = fmt::format("\r\n{:04}/{:02}/{:02} {:02}:{:02}:{:02}  {}",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond, msg);
          //logFile.WriteString(strInfo);
          //logFile.Close();
          std::ofstream ofs(strLogDir.string(), std::ios::app);
          ofs << strInfo;
      }
      catch(...)
      {
      }
//
// #ifdef USE_WINDOWS_DEBUG
//     OutputDebugString(msg); OutputDebugString("\n");
// #else
//     std::cerr << msg << std::endl;
// #endif
  }
} defaultErrorHandler;


// Error handler singleton
JsonRpcErrorHandler* JsonRpcErrorHandler::_errorHandler = &defaultErrorHandler;


// Easy API for log verbosity
int JsonRpc::getVerbosity() { return JsonRpcLogHandler::getVerbosity(); }
void JsonRpc::setVerbosity(int level) { JsonRpcLogHandler::setVerbosity(level); }


void JsonRpcUtil::log_str(int level, const char* buf, int len)
{
	JsonRpcLogHandler::getLogHandler()->log(level, buf, len);
}

#define MAX_LOG_LEVEL	9
static char const *indstr[MAX_LOG_LEVEL + 1] =
{
	"",						// level 0
	"  ",					// level 1
	"    ",					// level 2
	"      ",				// level 3
	"        ",				// level 4
	"          ",			// level 5
	"            ",			// level 6
	"              ",		// level 7
	"                ",		// level 8
	"                  ",	// level 9
};

FILE *JsonRpcUtil::jlogf = NULL;
BOOL JsonRpcUtil::jfail = FALSE;

void JsonRpcUtil::log(int level, const char* fmt, ...)
{
	time_t logDate = time(NULL) / (24 * 60 * 60);

	if (level > JsonRpcLogHandler::getVerbosity())
		return;


	int l = level > MAX_LOG_LEVEL? MAX_LOG_LEVEL: level;

	SYSTEMTIME t;
	::GetLocalTime(&t);

	fprintf(jlogf, "[%02d:%02d:%02d]%s", t.wHour, t.wMinute,  t.wSecond, indstr[l]);

	va_list va;
    va_start(va, fmt);
    vfprintf(jlogf, fmt, va);
	fprintf(jlogf, "\n");
	va_end(va);

	fflush(jlogf);
}


void JsonRpcUtil::error(const char* fmt, ...)
{
  va_list va;
  va_start(va, fmt);
  char buf[1024];
  vsnprintf(buf,sizeof(buf)-1,fmt,va);
  buf[sizeof(buf)-1] = 0;
  JsonRpcErrorHandler::getErrorHandler()->error(buf);
}




